package com.project.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.api.ApprovalApi;
import com.common.api.CommonFileApi;
import com.common.core.domain.AjaxResult;
import com.common.utils.QueryWrapperUtils;
import com.common.utils.SecurityUtils;
import com.common.utils.StringUtils;
import com.common.utils.bean.BizProcessMessages;
import com.common.utils.bean.ReflectionUtils;
import com.flowable.domain.vo.task.BpmTaskApproveReqVO;
import com.flowable.service.IFlowTaskService;
import com.project.comom.NumberDealUtils;
import com.project.domain.bo.BizBuyerContractBo;
import com.project.domain.entity.BizBuyerContract;
import com.project.domain.entity.SysUploadFile;
import com.project.mapper.BuyerContractMapper;
import com.project.mapper.UpLoadFileMapper;
import com.project.service.IBuyerContractService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;


/**
 * 横向出账合同
 */
@Service("biz_buyer_contract")
@Slf4j
public class BuyerContractServiceImpl extends ServiceImpl<BuyerContractMapper, BizBuyerContract> implements IBuyerContractService {

    @Autowired
    private BuyerContractMapper baseMapper;

    //流程引擎
    @Autowired
    private IFlowTaskService flowTaskService;
    //通用文件mapper
    @Autowired
    private UpLoadFileMapper fileMapper;
    //通用文件api
    @Autowired
    private CommonFileApi fileApi;
    //发起流程
    @Autowired
    private ApprovalApi approvalApi;


    private final static String module_name = "出账合同签订";

    private final static String approve_succ_msg = "审核通过";

    @Override
    public BizBuyerContract selectBizBuyerContractByID(String id) {
        BizBuyerContract buyerContract = baseMapper.selectBizBuyerContractById(id);
        String signature = buyerContract.getSignature();
        String fileIds = buyerContract.getFileIds();
        //处理合同金额
        buyerContract.setFeeAuthorize(NumberDealUtils.divide_bigDecimal(buyerContract.getFeeAuthorize()));
        buyerContract.setSourceFeeAuthorize(NumberDealUtils.divide_bigDecimal(buyerContract.getSourceFeeAuthorize()));

        //获取当前用户所有的代办列表
        Map<String, String> instanceTaskMap = approvalApi.getInstanceTaskMap(module_name);
        //设置IsAuditor和TaskId
        String processInstanceId = buyerContract.getProcessInstanceId();
        if (StringUtils.isNotEmpty(processInstanceId) && instanceTaskMap.containsKey(processInstanceId)) {
            buyerContract.setTaskId(instanceTaskMap.get(processInstanceId));
            buyerContract.setIsAuditor(true);
        } else {
            buyerContract.setIsAuditor(false);
        }

        //盖章页电子版
        List<Map<String, String>> signatureList = new ArrayList<>();
        if (StringUtils.hasText(signature)) {
            String[] split = signature.split(",");
            for (String s : split) {
                SysUploadFile uploadFile = fileMapper.selectById(s);
                if (uploadFile != null) {
                    Map<String, String> map = new HashMap<>();
                    map.put("id", s);
                    map.put("name", uploadFile.getUploadfilename());
                    signatureList.add(map);
                }
            }

            buyerContract.setSignatureList(signatureList);
        }

        //附件
        List<Map<String, String>> fileList = new ArrayList<>();
        if (StringUtils.hasText(fileIds)) {
            String[] split = fileIds.split(",");
            for (String s : split) {
                SysUploadFile uploadFile = fileMapper.selectById(s);
                if (uploadFile != null) {
                    Map<String, String> map = new HashMap<>();
                    map.put("id", s);
                    map.put("name", uploadFile.getUploadfilename());
                    fileList.add(map);
                }
            }

            buyerContract.setFileList(fileList);
        }

        return buyerContract;
    }

    @Override
    public List<BizBuyerContract> selectBizBuyerContractList(BizBuyerContractBo bo) {
        LambdaQueryWrapper<BizBuyerContract> lqw = buildQueryWrapper(bo,true);
        lqw.orderBy(true,false,BizBuyerContract::getCreateDate);
        List<BizBuyerContract> list = baseMapper.selectBizBuyerContractList(lqw);
        //获取当前用户所有的代办列表
        Map<String, String> instanceTaskMap = approvalApi.getInstanceTaskMap(module_name);

        for (BizBuyerContract u : list) {
            // 处理合同金额
            u.setFeeAuthorize(NumberDealUtils.divide_bigDecimal(u.getFeeAuthorize()));
            u.setSourceFeeAuthorize(NumberDealUtils.divide_bigDecimal(u.getSourceFeeAuthorize()));

            // 判断是否是审核人，并设置taskId
            String processInstanceId = u.getProcessInstanceId();
            if (StringUtils.isNotEmpty(processInstanceId) && instanceTaskMap.containsKey(processInstanceId)) {
                u.setTaskId(instanceTaskMap.get(processInstanceId));
                u.setIsAuditor(true);
            } else {
                u.setIsAuditor(false);
            }
        }
        return list;
    }

    @Override
    public List<HashMap<String, Integer>> listStatistics(BizBuyerContractBo bizBuyerContract) {
        LambdaQueryWrapper<BizBuyerContract> lqw = buildQueryWrapper(bizBuyerContract,false);
        lqw.groupBy(true,BizBuyerContract::getCheckstatus);
        return baseMapper.listStatistics(lqw);
    }

    @Override
    public List<BizBuyerContract> selectBizBuyerContractListConnectedTable(BizBuyerContractBo bo) {
        LambdaQueryWrapper<BizBuyerContract> lqw = buildQueryWrapper(bo,true);
        lqw.orderBy(true,false,BizBuyerContract::getCreateDate);
        List<BizBuyerContract> list = baseMapper.getBuyerContractListConnectedTable(lqw);
        list.forEach(e -> {
            //处理合同金额
            e.setFeeAuthorize(NumberDealUtils.divide_bigDecimal(e.getFeeAuthorize()));
            e.setSourceFeeAuthorize(NumberDealUtils.divide_bigDecimal(e.getSourceFeeAuthorize()));
        });
        return list;
    }

    /**
     *
     * @param bo
     * @param ConnectedTable 是否联表
     * @return
     */
    private LambdaQueryWrapper<BizBuyerContract> buildQueryWrapper(BizBuyerContractBo bo,Boolean ConnectedTable) {
        LambdaQueryWrapper<BizBuyerContract> lqw =new LambdaQueryWrapper<>();
        if (ConnectedTable){
            lqw.apply(StringUtils.isNotEmpty(bo.getCode()), "buyer.code like concat('%', {0}, '%')", bo.getCode());
            lqw.apply(StringUtils.isNotEmpty(bo.getName()), "buyer.name like concat('%', {0}, '%')", bo.getName());
        }else{
            lqw.like(StringUtils.isNotEmpty(bo.getCode()), BizBuyerContract::getCode, bo.getCode());
            lqw.like(StringUtils.isNotEmpty(bo.getName()), BizBuyerContract::getName, bo.getName());
        }
        lqw.eq(StringUtils.isNotEmpty(bo.getProjectStatusId()), BizBuyerContract::getProjectStatusId, bo.getProjectStatusId());
        lqw.ge(StringUtils.isNotNull(bo.getFeeAuthorizeMin()), BizBuyerContract::getFeeAuthorize, NumberDealUtils.multiply_bigDecimal(bo.getFeeAuthorizeMin()));
        lqw.le(StringUtils.isNotNull(bo.getFeeAuthorizeMax()), BizBuyerContract::getFeeAuthorize, NumberDealUtils.multiply_bigDecimal(bo.getFeeAuthorizeMax()) );
        lqw.in(StringUtils.isNotEmpty(bo.getUnitId()), BizBuyerContract::getUnitId, bo.getUnitId());
        lqw.like(StringUtils.isNotEmpty(bo.getSourceChargerName()), BizBuyerContract::getSourceChargerName, bo.getSourceChargerName());
        lqw.like(StringUtils.isNotEmpty(bo.getSourceProjectName()), BizBuyerContract::getSourceProjectName, bo.getSourceProjectName());
        lqw.in(StringUtils.isNotEmpty(bo.getSourceProjectType()), BizBuyerContract::getSourceProjectType, bo.getSourceProjectType());

        lqw.like(StringUtils.isNotEmpty(bo.getChargerName()), BizBuyerContract::getChargerName, bo.getChargerName());
        lqw.like(StringUtils.isNotEmpty(bo.getChargerTel()), BizBuyerContract::getChargerTel, bo.getChargerTel());
        lqw.like(StringUtils.isNotEmpty(bo.getYfUnitName()), BizBuyerContract::getYfUnitName, bo.getYfUnitName());
        lqw.like(StringUtils.isNotEmpty(bo.getYfCode()), BizBuyerContract::getYfCode, bo.getYfCode());
        lqw.like(StringUtils.isNotEmpty(bo.getYfChargerName()), BizBuyerContract::getYfChargerName, bo.getYfChargerName());
        lqw.like(StringUtils.isNotEmpty(bo.getYfTel()), BizBuyerContract::getYfTel, bo.getYfTel());
        lqw.like(StringUtils.isNotNull(bo.getSourceProjectID()), BizBuyerContract::getSourceProjectId, bo.getSourceProjectID());
        //处理时间
        lqw.ge(StringUtils.isNotEmpty(bo.getAuthorizeDateStart()), BizBuyerContract::getAuthorizeDate, changeDateString(bo.getAuthorizeDateStart(),"start"));
        lqw.le(StringUtils.isNotEmpty(bo.getAuthorizeDateEnd()), BizBuyerContract::getAuthorizeDate, changeDateString(bo.getAuthorizeDateEnd(),"end"));

        //多选栏审核状态
        lqw.in(StringUtils.isNotEmpty(bo.getCheckStatusArr()), BizBuyerContract::getCheckstatus, bo.getCheckStatusArr());
        //上方的审核状态
        lqw.eq(StringUtils.isNotEmpty(bo.getCheckStatus()), BizBuyerContract::getCheckstatus, bo.getCheckStatus());

        QueryWrapperUtils.getParams_contract(lqw,SecurityUtils.getLoginUser().getUser());
        return lqw;
    }


    @Override
    public AjaxResult insertBizBuyerContract(BizBuyerContract bizBuyerContract) {
        Integer submitType = bizBuyerContract.getSubmitType();
        // 处理合同金额和原合同金额
        bizBuyerContract.setFeeAuthorize(NumberDealUtils.multiply_bigDecimal(bizBuyerContract.getFeeAuthorize()));
        bizBuyerContract.setSourceFeeAuthorize(NumberDealUtils.multiply_bigDecimal(bizBuyerContract.getSourceFeeAuthorize()));

        switch (submitType) {
            case 2: // 保存并通过
                bizBuyerContract = ReflectionUtils.updateFields(bizBuyerContract, BizBuyerContract.class);
                bizBuyerContract.setCheckstatus(String.valueOf(submitType));
                bizBuyerContract.setProcessInstanceId("0");
                break;
            case 1: // 提交
                if (!this.save(bizBuyerContract)) {
                    return AjaxResult.error(BizProcessMessages.SAVE_FAIL);
                }
                String processInstanceId = null;
                try {
                    //发起流程 业务状态由流程引擎更新
                    processInstanceId = approvalApi.businessEntryApproval(bizBuyerContract.getId(), module_name);
                } catch (Exception e) {
                    AjaxResult.error(BizProcessMessages.SAVE_PARTIAL_SUCCESS);
                }

                return StringUtils.isEmpty(processInstanceId)
                        ? AjaxResult.error(BizProcessMessages.SAVE_PARTIAL_SUCCESS)
                        : AjaxResult.success(BizProcessMessages.SAVE_SUCCESS);
            default: // 处理 -1（暂存）及其他情况
                bizBuyerContract.setCheckstatus(String.valueOf(submitType));
                break;
        }

        return this.save(bizBuyerContract)
                ? AjaxResult.success(BizProcessMessages.SAVE_SUCCESS)
                : AjaxResult.error(BizProcessMessages.SAVE_FAIL);
    }


    public AjaxResult updateBizBuyerContract(BizBuyerContract bizBuyerContract) {
        Integer submitType = bizBuyerContract.getSubmitType();
        // 处理合同金额和原合同金额
        bizBuyerContract.setFeeAuthorize(NumberDealUtils.multiply_bigDecimal(bizBuyerContract.getFeeAuthorize()));
        bizBuyerContract.setSourceFeeAuthorize(NumberDealUtils.multiply_bigDecimal(bizBuyerContract.getSourceFeeAuthorize()));

        switch (submitType) {
            case 2: // 保存并通过
                // 当前用户是否是审批人
                boolean isAuditor = bizBuyerContract.getIsAuditor();
                // 审批人直接审核（仅适用于提交类型2且为当前审核人的情况）
                if (isAuditor) {
                    if (this.updateById(bizBuyerContract)) {
                        BpmTaskApproveReqVO bta = new BpmTaskApproveReqVO();
                        bta.setId(bizBuyerContract.getTaskId());
                        bta.setReason(approve_succ_msg);
                        try {
                            flowTaskService.approveTask(SecurityUtils.getUserId(), bta);
                        } catch (Exception e) {
                            return AjaxResult.error(BizProcessMessages.SAVE_SUCCESS_APPROVE_FAIL, e.getMessage());
                        }

                        return AjaxResult.success(BizProcessMessages.SAVE_SUCCESS);
                    }
                    return AjaxResult.error(BizProcessMessages.SAVE_FAIL);
                }
                //处理非当前审批人保存并通过
                bizBuyerContract = ReflectionUtils.updateFields(bizBuyerContract, BizBuyerContract.class);
                bizBuyerContract.setProcessInstanceId("0");
                //只有管理员才会有非当前审核人的情况下有 "保存并提交"按钮,审核完后的结果只能是审核通过
                bizBuyerContract.setCheckstatus(String.valueOf(submitType));
                bizBuyerContract.setCode(getContractCode());
                break;
            case 1:
                //暂存转提交
                if (!this.updateById(bizBuyerContract)) {
                    return AjaxResult.error(BizProcessMessages.SAVE_FAIL);
                }
                String returnProcessInstanceId = null;
                try {
                    returnProcessInstanceId = approvalApi.businessEntryApproval(bizBuyerContract.getId(), module_name);
                } catch (Exception e) {
                    return AjaxResult.error(BizProcessMessages.SAVE_PARTIAL_SUCCESS, e.getMessage());
                }

                return StringUtils.isEmpty(returnProcessInstanceId)
                        ? AjaxResult.warn(BizProcessMessages.SAVE_PARTIAL_SUCCESS)
                        : AjaxResult.success(BizProcessMessages.SAVE_SUCCESS);
            case -1: // 暂存
                return this.updateById(bizBuyerContract)
                        ? AjaxResult.success(BizProcessMessages.SAVE_SUCCESS)
                        : AjaxResult.error(BizProcessMessages.SAVE_FAIL);
            default:
                break;
        }

        return this.updateById(bizBuyerContract)
                ? AjaxResult.success(BizProcessMessages.SAVE_SUCCESS)
                : AjaxResult.error(BizProcessMessages.SAVE_FAIL);
    }


    @Override
    public Boolean deleteBizBuyerContractByIds(String[] ids) {
        List<BizBuyerContract> bizBuyerContracts = this.listByIds(Arrays.asList(ids));
        List<String> fileList = new ArrayList();
        //删除记录所携带的文件
        bizBuyerContracts.forEach(e -> {
            String fileIds = e.getFileIds();
            String signature = e.getSignature();
            if (StringUtils.isNotEmpty(fileIds)) {
                String[] split = fileIds.split(",");
                fileList.addAll(Arrays.asList(split));
            }
            if (StringUtils.isNotEmpty(signature)) {
                String[] split = signature.split(",");
                fileList.addAll(Arrays.asList(split));
            }
        });

        for (String fileId : fileList) {
            try {
                fileApi.delFile(fileId);
            } catch (Exception e) {
              log.error("删除文件失败,文件id:{}",fileId);
            }
        }

        return this.removeByIds(Arrays.asList(ids));
    }

    @Override
    public Boolean deleteBizBuyerContractById(String id) {
        return this.removeById(id);
    }


    @Override
    public List<BizBuyerContract> getHxZxXmByName(String projectName) {
        if (StringUtils.isEmpty(projectName)) return null;
        //查横向和纵向项目
        QueryWrapper<BizBuyerContract> wrapper = new QueryWrapper<>();
        wrapper.and(w -> w.like("vp.code", projectName)
                        .or()
                        .like("vp.name", projectName)
                        .or()
                        .like("vp.charger_name", projectName)
                        .or()
                        .like("vp.charger_code", projectName))
                .in("vp.project_class", "zXProject", "yfContract")
                .eq("vp.checkStatus","2");
        List<BizBuyerContract> allProjectEntities = baseMapper.getHxZxXmByName(wrapper);
        allProjectEntities.forEach(e -> {
            BigDecimal sourceFeeAuthorize = e.getSourceFeeAuthorize();
            if (sourceFeeAuthorize != null && !sourceFeeAuthorize.equals(BigDecimal.ZERO)) {
                e.setSourceFeeAuthorize(NumberDealUtils.divide_bigDecimal(sourceFeeAuthorize));
            }
        });
        return allProjectEntities;
    }


    @Override
    public String getContractCode() {
        String firstPrefix="甲";
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy");
        String year = dateFormat.format(new Date());
        String prefix = firstPrefix + year;
        String contractCode = baseMapper.getContractCode(prefix);
        return contractCode;
    }

    @Override
    public void updateBusinessStatus(String tableName, String businessId, String checkStatus, String sysUserId) {
        if ("2".equals(checkStatus)){
            String contractCode = getContractCode();
            UpdateWrapper<BizBuyerContract> update=new UpdateWrapper();
            update.set(StringUtils.isNotEmpty(contractCode),"code",contractCode);
            update.eq("id",businessId);
            this.update(update);
        }
    }

    /**
     * 处理其他时间字符串
     * @param dateStr
     * @param startOrEnd
     * @return
     */
    public String changeDateString(String dateStr,String startOrEnd){
        if(StringUtils.isNotBlank(dateStr)){
            int strLength = dateStr.length();
            if(startOrEnd.equals("start")){
                if(strLength == 4){
                    dateStr = dateStr + "-01-01 00:00:00";
                }else if(strLength == 7){
                    dateStr = dateStr + "-01 00:00:00";
                }
            }else{
                if(strLength == 4){
                    dateStr = dateStr + "-12-31 23:59:59";
                }else if(strLength == 7){
                    dateStr += "-01"; // 默认到每月的第一天
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                    LocalDate date = LocalDate.parse(dateStr, formatter);
                    LocalDate lastDayOfMonth = date.withDayOfMonth(date.lengthOfMonth());
                    DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                    dateStr = lastDayOfMonth.format(outputFormatter) + " 23:59:59";
                }
            }
        }
        return dateStr;
    }

}
